package cn.schoolwow.quickdao.module.database.dml.instance.kit;

import cn.schoolwow.quickdao.domain.database.dml.CompareInstanceListResult;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.module.database.dml.common.domain.ManipulationOption;
import cn.schoolwow.quickdao.module.database.dml.common.service.GetInstanceReasonMapCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.TruncateTableFlow;
import cn.schoolwow.quickdao.module.database.dml.instance.service.compare.CompareInstanceListFlow;
import cn.schoolwow.quickdao.module.database.dml.instance.service.delete.DeleteInstanceArrayCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.delete.DeleteInstanceCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.insert.InsertIgnoreInstanceArrayFlow;
import cn.schoolwow.quickdao.module.database.dml.instance.service.insert.InsertIgnoreInstanceFlow;
import cn.schoolwow.quickdao.module.database.dml.instance.service.insert.InsertInstanceArrayCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.insert.InsertInstanceCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.save.SaveInstanceArrayCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.save.SaveInstanceFlow;
import cn.schoolwow.quickdao.module.database.dml.instance.service.update.UpdateInstanceArrayCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dml.instance.service.update.UpdateInstanceCompositeBusiness;
import cn.schoolwow.quickdao.module.database.dql.condition.domain.SFunction;
import cn.schoolwow.quickdao.module.database.parent.flow.executor.ExecuteUpdateConnectionFlow;
import cn.schoolwow.quickdao.module.database.parent.kit.DatabaseDAOImpl;
import cn.schoolwow.quickdao.util.LambdaUtils;
import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.domain.FlowContext;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class DatabaseManipulationInstanceImpl extends DatabaseDAOImpl implements DatabaseManipulationInstance {
    public DatabaseManipulationInstanceImpl(QuickFlow quickFlow) {
        super(quickFlow);
    }

    @Override
    public Map<Object,String> getReasonInstanceMap(Object[] instances) {
        if(null==instances||instances.length==0){
            return null;
        }
        ManipulationOption manipulationOption = quickFlow.getContextThreadLocalInstanceData(ManipulationOption.class);
        FlowContext flowContext = quickFlow.startFlow(new GetInstanceReasonMapCompositeBusiness())
                .putTemporaryData("instances", instances)
                .execute();
        Map<Object,String> instanceReasonMap = (Map<Object,String>) flowContext.getData("instanceReasonMap");
        return instanceReasonMap;
    }

    @Override
    public int insert(Object instance) {
        if (null == instance) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new InsertInstanceCompositeBusiness())
                .putData("instance", instance)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int insert(Object[] instances) {
        if (null == instances || instances.length == 0) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new InsertInstanceArrayCompositeBusiness())
                .putData("instances", instances)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int insert(Collection instanceCollection) {
        if (null == instanceCollection || instanceCollection.size() == 0) {
            return 0;
        }
        return insert(instanceCollection.toArray(new Object[0]));
    }

    @Override
    public int insertIgnore(Object instance) {
        if (null == instance) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new InsertIgnoreInstanceFlow())
                .putData("instance", instance)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int insertIgnore(Object[] instances) {
        if (null == instances || instances.length == 0) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new InsertIgnoreInstanceArrayFlow())
                .putData("instances", instances)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int insertIgnore(Collection instanceCollection) {
        return insertIgnore(instanceCollection.toArray(new Object[0]));
    }

    @Override
    public int update(Object instance) {
        if (null == instance) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new UpdateInstanceCompositeBusiness())
                .putData("instance", instance)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int update(Object[] instances) {
        if (null == instances || instances.length == 0) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new UpdateInstanceArrayCompositeBusiness())
                .putData("instances", instances)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int update(Collection instanceCollection) {
        if (null == instanceCollection || instanceCollection.size() == 0) {
            return 0;
        }
        return update(instanceCollection.toArray(new Object[0]));
    }

    @Override
    public int save(Object instance) {
        if (null == instance) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new SaveInstanceFlow())
                .putData("instance", instance)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int save(Object[] instances) {
        if (null == instances || instances.length == 0) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new SaveInstanceArrayCompositeBusiness())
                .putData("instances", instances)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int save(Collection instanceCollection) {
        if (null == instanceCollection || instanceCollection.size() == 0) {
            return 0;
        }
        return save(instanceCollection.toArray(new Object[0]));
    }

    @Override
    public int delete(Object instance) {
        if (null == instance) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new DeleteInstanceCompositeBusiness())
                .putData("instance", instance)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int delete(Object[] instances) {
        if (null == instances || instances.length == 0) {
            return 0;
        }
        FlowContext flowContext = quickFlow.startFlow(new DeleteInstanceArrayCompositeBusiness())
                .putData("instances", instances)
                .execute();
        return getEffect(flowContext);
    }

    @Override
    public int delete(Collection instanceCollection) {
        if (null == instanceCollection || instanceCollection.size() == 0) {
            return 0;
        }
        return delete(instanceCollection.toArray(new Object[0]));
    }

    @Override
    public int delete(Class clazz, long id) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        return delete(clazz, entity.id.column, id);
    }

    @Override
    public int delete(Class clazz, String id) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        return delete(clazz, entity.id.column, id);
    }

    @Override
    public int delete(Class clazz, String field, Object value) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        String columnName = entity.getColumnNameByFieldName(field);
        return delete(entity.tableName, columnName, value);
    }

    @Override
    public int delete(String tableName, String columnName, Object value) {
        String updateSQL = "delete from " + quickDAOConfig.databaseContext.databaseProvider.escape(tableName) + " where " + quickDAOConfig.databaseContext.databaseProvider.escape(columnName) + " = ?";
        List parameters = Arrays.asList(value);
        FlowContext flowContext = quickFlow.startFlow(new ExecuteUpdateConnectionFlow())
                .putTemporaryData("name", "根据指定列字段删除记录")
                .putTemporaryData("sql", updateSQL)
                .putTemporaryData("parameters", parameters)
                .execute();
        int effect = flowContext.checkData("effect", int.class);
        return effect;
    }

    @Override
    public <T> int delete(Class<T> clazz, SFunction<T, ?> field, Object value) {
        String fieldName = LambdaUtils.resolveLambdaProperty(field);
        return delete(clazz, fieldName, value);
    }

    @Override
    public int clear(Class clazz) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        return clear(entity.tableName);
    }

    @Override
    public int clear(String tableName) {
        FlowContext flowContext = quickFlow.startFlow(new ExecuteUpdateConnectionFlow())
                .putTemporaryData("name", "清空表")
                .putTemporaryData("sql", "delete from " + quickDAOConfig.databaseContext.databaseProvider.escape(tableName))
                .execute();
        int effect = flowContext.checkData("effect", int.class);
        return effect;
    }

    @Override
    public int truncate(Class clazz) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        return truncate(entity.tableName);
    }

    @Override
    public int truncate(String tableName) {
        FlowContext flowContext = quickFlow.startFlow(new TruncateTableFlow())
                .putCurrentCompositeFlowData("tableName", tableName)
                .execute();
        int effect = (int) flowContext.checkData("effect");
        return effect;
    }

    @Override
    public <T> CompareInstanceListResult<T> compareInstanceList(Collection<T> currentInstances) {
        if (null == currentInstances || currentInstances.size() == 0) {
            return new CompareInstanceListResult<>();
        }
        FlowContext flowContext = quickFlow.startFlow(new CompareInstanceListFlow())
                .putData("currentInstances", currentInstances)
                .execute();
        CompareInstanceListResult<T> compareInstanceListResult = flowContext.checkInstanceData(CompareInstanceListResult.class);
        return compareInstanceListResult;
    }

    @Override
    public <T> CompareInstanceListResult<T> compareInstanceList(Collection<T> currentInstances, Collection<T> totalInstances) {
        FlowContext flowContext = quickFlow.startFlow(new CompareInstanceListFlow())
                .putTemporaryData("currentInstances", currentInstances)
                .putTemporaryData("totalInstances", totalInstances)
                .execute();
        CompareInstanceListResult<T> compareInstanceListResult = flowContext.checkInstanceData(CompareInstanceListResult.class);
        return compareInstanceListResult;
    }
}
